package pl.enigmatic.input;

import java.awt.Graphics;

import javax.swing.JTextField;

import pl.enigmatic.math.MathUtil;
import pl.enigmatic.util.Strings;


public class IntegerInput extends JTextField {

	/** */
	private static final long serialVersionUID = 1L;

	private int value;

	private final int min;
	private final int max;
	private final int step = 1;

	public IntegerInput(final int min, final int max) {
		this.min = min;
		this.max = Math.max(min, max);
		setValue(0);
		new MouseValueIncreaser(new MouseValueIncreaser.Target() {

			@Override
			public void increaseValue(final int steps) {
				setValue(value + step * steps);
			}
		}).applyTo(this);
	}

	public IntegerInput() {
		this(Integer.MIN_VALUE, Integer.MAX_VALUE);
	}

	private int parse(String string) {
		if (Strings.nonEmpty(string)) {
			try {
				final boolean minus = string.startsWith("-");
				string = minus ? string.substring(1) : string;
				string = (minus ? "-" : "") + string.replaceAll("[^1234567890]", "");
				final int x = MathUtil.clamp(min, max, Integer.parseInt(string));
				return x;
			} catch (final Exception e) {}
		}
		return value;
	}

	@Override
	protected void paintComponent(final Graphics g) {
		final String txt = getText();
		final int v = parse(txt);
		if ("-".equals(txt) || "".equals(txt)) {
			_setValue(0);
			setTextSuper(txt);
		} else if (!txt.startsWith("-") && !Strings.isNumeric(txt.substring(0, 1))) {
			setTextSuper("");
		} else {
			_setValue(v);
		}
		super.paintComponent(g);
	}

	@Override
	public void setText(final String t) {}

	private void setTextSuper(final String t) {
		if (!t.equals(getText())) {
			final int start = getSelectionStart();
			final int end = getSelectionEnd();
			super.setText(t);
			setSelectionStart(Math.max(start, 0));
			setSelectionEnd(Math.max(end, 0));
		}
	}

	private void _setValue(final int value) {
		final int old = this.value;
		this.value = value;
		setTextSuper(Integer.toString(this.value));
		if (old != value) {
			onValueChanged(old);
		}
	}

	protected void onValueChanged(final int old) {}

	public void setValue(final int value) {
		_setValue(MathUtil.clamp(min, max, value));
		repaint();
	}

	public int getValue() {
		return value;
	}

	public int getStep() {
		return step;
	}

}
